﻿//  Copyright (c) 2011 Ray Liang (http://www.dotnetage.com)
//  Licensed MIT: http://www.opensource.org/licenses/mit-license.php

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Security;
using DNA.Mvc.Exporting;
using DNA.OpenAPI.BlogML;
using DNA.Utility;

namespace DNA.Mvc.Publishing
{
    public class BlogMLExporter : Exporter
    {
        private IPubService srv;

        public BlogMLExporter(IPubService service)
        {
            srv = service;
        }

        public override string Name
        {
            get { return "bml"; }
        }

        public override string Description
        {
            get
            {
                return "Export the publising data (including categories,posts,comments and authors) to BlogML format.";
            }
        }

        public override void Execute(ExportingContext context)
        {
            var pkgPath = context.Destination + (context.Destination.EndsWith("\\") ? "" : "\\");
            var filename = pkgPath + "blog.xml";

            var web = GetMatch<Web>(context);

            //context.Data["Web"] as Web;
            var rootCategory = srv.FindCategory(web.Name);

            var bmlBlog = new BlogMLBlog()
            {
                Title = web.Title,
                RootUrl = UrlResolver.Resolve(context.HttpContext, web),
                SubTitle = this.Description,
                DateCreated = web.Created,
                Authors = new List<BlogMLAuthor>(),
                Categories = new List<BlogMLCategory>(),
                Posts = new List<BlogMLPost>()
            };

            //Add all users.
            var posts = srv.GetDescendantArticles(rootCategory.ID);
            AddAuthors(bmlBlog, posts);

            var cats = srv.GetCategories(web.Name);
            AddCategories(bmlBlog, cats);

            AddPosts(bmlBlog, posts);

            XmlSerializerUtility.SerializeToXmlFile<BlogMLBlog>(filename, bmlBlog);

            context.Installers.Add("bml", "<config src=\"blog.xml\" />");
        }

        private void AddAuthors(BlogMLBlog blog, IQueryable<Article> articles)
        {
            var userNames = articles.Select(a => a.UserName).Distinct();
            foreach (var userName in userNames)
            {
                var user = Membership.GetUser(userName);

                if (user != null)
                {
                    blog.Authors.Add(new BlogMLAuthor()
                    {
                        Approved = user.IsApproved,
                        Email = user.Email,
                        ID = userName,
                        Title = user.GetDisplayName(),
                        DateModified = user.LastActivityDate
                    });
                }
            }
        }

        private void AddCategories(BlogMLBlog blog, IEnumerable<Category> categories)
        {
            if (categories != null)
            {
                foreach (var cat in categories)
                {
                    blog.Categories.Add(new BlogMLCategory()
                    {
                        Description = cat.Description,
                        ID = cat.ID.ToString(),
                        ParentRef = cat.ParentID.ToString(),
                        Title = cat.Title,
                        Approved = true,
                        DateCreated = DateTime.Now,
                        DateModified = DateTime.Now
                    });
                }
            }

        }

        private void AddPosts(BlogMLBlog blog, IQueryable<Article> posts)
        {
            if ((posts != null) && (posts.Count() > 0))
            {
                foreach (var post in posts)
                {
                    var bmlPost = new BlogMLPost()
                    {
                        ID = post.ID.ToString(),
                        DateCreated = post.Posted,
                        DateModified = post.LastModified,
                        HasExcerpt = !string.IsNullOrEmpty(post.Summary),
                        Excerpt = new BlogMLContent()
                        {
                            Text = post.Summary,
                            ContentType = BlogMLContentTypes.Text
                        },
                        Title = post.Title,
                        PostUrl = post.PermaLink,
                        PostType = BlogPostTypes.Article,
                        Content = new BlogMLContent()
                        {
                            Text = post.Body,
                            ContentType = post.ContentFormat == 1 ? BlogMLContentTypes.XHtml : BlogMLContentTypes.Text
                        },
                        Approved = post.IsPublished,
                        Views=(uint)post.TotalReads, 
                        Authors = new List<BlogMLAuthorRef>(),
                        Categories = new List<BlogMLCategoryRef>()
                    };

                    var author = new BlogMLAuthorRef()
                    {
                        Ref = post.UserName
                    };

                    bmlPost.Authors.Add(author);

                    if (post.Comments.Count > 0)
                        AddComments(bmlPost, post);

                    blog.Posts.Add(bmlPost);
                    bmlPost.Categories.Add(new BlogMLCategoryRef() { Ref = post.CategoryID.ToString() });

                    if (!string.IsNullOrEmpty(post.Categories))
                    {
                        var postCats = post.Categories.Split(',');
                        foreach (var c in postCats)
                            bmlPost.Categories.Add(new BlogMLCategoryRef() { Ref = c });
                    }
                }
            }
        }

        private void AddComments(BlogMLPost bmlPost, Article post)
        {
            //if (bmlPost.Authors == null)
            //    bmlPost.Authors = new List<BlogMLAuthorRef>();

            //bmlPost.Authors.Add(new BlogMLAuthorRef() { Ref = post.UserName });

            var comments = post.Comments;

            if ((comments != null) && (comments.Count > 0))
            {
                bmlPost.Trackbacks = new List<BlogMLTrackback>();
                bmlPost.Comments = new List<BlogMLComment>();

                foreach (var comm in comments)
                {
                    if ((comm.IsPingback) || (comm.IsTrackback))
                    {
                        bmlPost.Trackbacks.Add(new BlogMLTrackback()
                        {
                            Approved = true,
                            DateCreated = comm.Posted,
                            DateModified = comm.Posted,
                            ID = comm.ID.ToString(),
                            Title = comm.Title,
                            Url = comm.WebSite
                        });
                    }
                    else
                    {
                        bmlPost.Comments.Add(new BlogMLComment()
                        {
                            ID = comm.ID.ToString(),
                            Approved = true,
                            Content = new BlogMLContent() { Text = comm.Body },
                            DateCreated = comm.Posted,
                            DateModified = comm.Posted,
                            Title = comm.Title,
                            UserEMail = comm.Email,
                            UserName = comm.UserName,
                            UserUrl = comm.WebSite
                        });
                    }
                }
            }
        }
    }
}
